<script setup lang="ts">
import type { Key } from 'ant-design-vue/es/vc-tree/interface';

import type { Nullable } from '@vben/types';

import type {
  ContextMenuItem,
  TreeActionItem,
  TreeActionType,
  TreeItem,
} from '#/components/tree';

import { h, onMounted, ref, unref } from 'vue';

import {
  DeleteOutlined,
  EditOutlined,
  PlusSquareOutlined,
  TrademarkOutlined,
} from '@ant-design/icons-vue';
import { Button, Checkbox, Tag } from 'ant-design-vue';

import { BaseOrgApi } from '#/api/basic/user/baseOrg';
import { BasicTree } from '#/components/tree';
import { ORG_TYPE_TAG_MAP, ScopeTypeEnum } from '#/enums/base';
import { PermCode } from '#/enums/perm';
import { useMessage } from '#/hooks/web/useMessage';
import { $t } from '#/locales';
import {
  eachTree,
  findChildrenByParentId,
  findNodeByKey,
} from '#/utils/helper/treeHelper';
import BindRoleModal from '#/views/_core/common/bindRole/index.vue';

defineOptions({
  name: 'BaseOrg树结构',
  inheritAttrs: false,
});
const props = withDefaults(defineProps<Props>(), {
  query: false,
});
const emit = defineEmits<Emits>();
interface Props {
  query?: boolean;
}
interface Emits {
  (e: 'select', parent: TreeItem, current: TreeItem, childrenIds: Key[]): void;
  (e: 'add', parent: TreeItem): void;
  (e: 'edit', parent: TreeItem, current: TreeItem): void;
  (e: 'change', type: string): void;
  (e: 'reset'): void;
}

const { createMessage, createConfirm } = useMessage();
const treeRef = ref<Nullable<TreeActionType>>(null);
const treeData = ref<TreeItem[]>([]);
const treeLoading = ref<boolean>(false);
const recursion = ref<boolean>(false);
const bindRoleRef = ref<any>();
const permCode = PermCode.basic.user.baseOrg;

function getTree() {
  const treeR = unref(treeRef);
  if (!treeR) {
    throw new Error('树结构加载失败,请刷新页面');
  }
  return treeR;
}

onMounted(() => {
  fetch();
});

// 加载数据
async function fetch() {
  try {
    treeLoading.value = true;
    treeData.value = (await BaseOrgApi.tree({})) as unknown as TreeItem[];
    eachTree(
      treeData.value,
      (item) => {
        item.key = item.id;
        item.title = item.name;
        item.slots = { titleBefore: 'titleBefore' };
        return item;
      },
      {},
    );
    setTimeout(() => {
      getTree().filterByLevel(2);
    }, 0);
  } finally {
    treeLoading.value = false;
  }
}

// 选择节点
function handleSelect(keys: Key[]) {
  if (keys[0]) {
    const node = findNodeByKey(keys[0], treeData.value);
    const parent = findNodeByKey(node?.parentId, treeData.value);
    let childrenIds: Key[] = [];
    childrenIds = recursion.value
      ? findChildrenByParentId(keys[0], treeData.value)
      : [node.id];
    emit('select', parent, node, childrenIds);
  }
}

let actionList: TreeActionItem[] = [];
let getRightMenuList = (_: any): ContextMenuItem[] => {
  return [];
};

if (!props.query) {
  // 悬停图标
  actionList = [
    {
      auth: permCode.add,
      render: (node: any) => {
        return h(PlusSquareOutlined, {
          class: 'ml-2',
          title: $t('common.title.add'),
          onClick: (e: Event) => {
            e?.stopPropagation();
            e?.preventDefault();
            emit('add', findNodeByKey(node.id as Key, treeData.value));
          },
        });
      },
    },
    {
      auth: permCode.edit,
      render: (node: any) => {
        return h(EditOutlined, {
          class: 'ml-2',
          title: $t('common.title.edit'),
          onClick: (e: Event) => {
            e?.stopPropagation();
            e?.preventDefault();
            const current = findNodeByKey(node?.id as Key, treeData.value);
            const parent = findNodeByKey(node?.parentId as Key, treeData.value);
            emit('edit', parent, current);
          },
        });
      },
    },
    {
      auth: permCode.bind,
      render: (node: any) => {
        return h(TrademarkOutlined, {
          class: 'ml-2',
          title: '绑定',
          onClick: (e: Event) => {
            e?.stopPropagation();
            e?.preventDefault();
            bindRoleRef.value.setData({
              scopeType: ScopeTypeEnum.ORG,
              id: node?.id,
            });
            bindRoleRef.value.open();
          },
        });
      },
    },
    {
      auth: permCode.delete,
      render: (node: any) => {
        return h(DeleteOutlined, {
          class: 'ml-2',
          title: $t('common.title.delete'),
          style: { color: '#ED6F6F' },
          onClick: (e: Event) => {
            e?.stopPropagation();
            e?.preventDefault();
            batchDelete([node.id as string]);
          },
        });
      },
    },
  ];

  // 右键菜单
  getRightMenuList = (node: any): ContextMenuItem[] => {
    return [
      {
        label: $t('common.title.addChildren'),
        auth: permCode.add,
        handler: () => {
          emit('add', findNodeByKey(node.id as Key, treeData.value));
        },
        icon: 'ant-design:plus-outlined',
      },
      {
        label: $t('common.title.edit'),
        auth: permCode.edit,
        handler: () => {
          const current = findNodeByKey(node?.id as Key, treeData.value);
          const parent = findNodeByKey(node?.parentId as Key, treeData.value);
          emit('edit', parent, current);
        },
        icon: 'ant-design:edit-outlined',
      },
      {
        label: $t('common.title.delete'),
        auth: permCode.delete,
        handler: () => {
          batchDelete([node?.id as string]);
        },
        icon: 'ant-design:delete-outlined',
      },
    ];
  };
}

// 点击树外面的 新增
function handleAdd() {
  emit('add', findNodeByKey('0', treeData.value));
}

// 执行批量删除
async function batchDelete(ids: string[]) {
  createConfirm({
    iconType: 'warning',
    content: '选中节点及其子结点将被永久删除, 是否确定删除？',
    onOk: async () => {
      try {
        await BaseOrgApi.remove(ids);
        await fetch();
        createMessage.success($t('common.tips.deleteSuccess'));
      } catch {}
    },
  });
}

// 点击树外面的 批量删除
function handleBatchDelete() {
  const checkedKeys = getTree().getCheckedKeys();
  const checked = getTree().getCheckStrictly()
    ? (checkedKeys as any).checked
    : checkedKeys;

  if (!checked || checked.length <= 0) {
    createMessage.warn($t('common.tips.pleaseSelectTheData'));
    return;
  }
  batchDelete(checked as string[]);
}

// 重置
function handleReset() {
  getTree().setSelectedKeys([]);
  emit('reset');
}

// 选择 本级及子级
function handleQuery() {
  handleSelect(getTree().getSelectedKeys() as string[]);
}

function changeDisplay() {
  emit('change', '2');
}

defineExpose({ fetch });
</script>

<template>
  <div class="overflow-hidden">
    <div v-if="query" class="mb-1">
      <Button class="mr-2" type="primary" @click="handleReset()">重置</Button>
      <Checkbox v-model:checked="recursion" @change="handleQuery()">
        本级及子级
      </Checkbox>
    </div>
    <div v-else class="mb-1">
      <Button
        v-hasAnyPermission="[permCode.switch]"
        type="primary"
        class="mr-2"
        @click="changeDisplay()"
      >
        切换
      </Button>
      <Button
        v-hasAnyPermission="[permCode.add]"
        class="mr-2"
        @click="handleAdd()"
      >
        {{ $t('common.title.addRoot') }}
      </Button>
      <Button
        v-hasAnyPermission="[permCode.delete]"
        class="mr-2"
        @click="handleBatchDelete()"
      >
        {{ $t('common.title.delete') }}
      </Button>
      <Button class="mr-2" @click="fetch()">
        {{ $t('common.redo') }}
      </Button>
    </div>
    <BasicTree
      ref="treeRef"
      :field-names="{ key: 'id', title: 'name' }"
      :action-list="actionList"
      :before-right-click="getRightMenuList"
      :click-row-to-expand="false"
      :loading="treeLoading"
      checkable
      :title="$t('basic.user.baseOrg.table.title')"
      :tree-data="treeData"
      check-strictly
      highlight
      search
      toolbar
      @select="handleSelect"
    >
      <template #titleBefore="item">
        <template v-if="item.echoMap?.type">
          <Tag :color="ORG_TYPE_TAG_MAP.get(item.type)">
            {{ item.echoMap?.type }}
          </Tag>
        </template>
      </template>
    </BasicTree>
    <BindRoleModal ref="bindRoleRef" />
  </div>
</template>
<style lang="scss" scoped></style>
